/*****************************************************************************
*    Copyright (C)2008 Ali Corporation. All Rights Reserved.
*
*    File:    tun_tda18250.c
*
*    Description:    This file contains tda18250 basic function in LLD. 
*    History:
*           Date            Athor        Version          Reason
*	    ============	=============	=========	=================
*	1.  20080520		Trueve Hu		 Ver 0.1	Create file.
*	
*****************************************************************************/

/*
  Copyright (C) 2006-2009 NXP B.V., All Rights Reserved.
  This source code and any compilation or derivative thereof is the proprietary
  information of NXP B.V. and is confidential in nature. Under no circumstances
  is this software to be  exposed to or placed under an Open Source License of
  any type without the expressed written permission of NXP B.V.
 *
 * \file          main.c
 *
 *                3
 *
 * \date          %modify_time%
 *
 * \brief         Sample application code of the NXP TDA18250 driver.
 *
 * REFERENCE DOCUMENTS :
 *                TDA18250_Driver_User_Guide.pdf
 *
 * Detailed description may be added here.
 *
 * \section info Change Information
 *
*/

//*--------------------------------------------------------------------------------------
//* Include Standard files
//*--------------------------------------------------------------------------------------
#include "tmNxTypes.h"
#include "tmCompId.h"
#include "tmFrontEnd.h"
#include "tmbslFrontEndTypes.h"

//*--------------------------------------------------------------------------------------
//* Include Driver files
//*--------------------------------------------------------------------------------------
#include "tmddTDA18250.h"
#include "tmbslTDA18250.h"


#include <sys_config.h>
#include <retcode.h>
#include <types.h>

#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/i2c/i2c.h>
#include <osal/osal_task.h>

#include "Tun_tda18250.h"

#define TDA18250_PRINTF(...) //libc_printf

//#define TDA18250_PRINTF		libc_printf

static struct QAM_TUNER_CONFIG_EXT * tda18250_dev_id[MAX_TUNER_SUPPORT_NUM] = {NULL};
static UINT32 tda18250_tuner_cnt = 0;

static OSAL_ID tun_tda18250_mutex_arr[2] = {0,0};

static UINT32 tda18250_tuner_i2c = I2C_TYPE_SCB0;

//*--------------------------------------------------------------------------------------
//* Prototype of function to be provided by customer
//*--------------------------------------------------------------------------------------
tmErrorCode_t 	UserWrittenI2CRead(tmUnitSelect_t tUnit,UInt32 AddrSize, UInt8* pAddr,UInt32 ReadLen, UInt8* pData);
tmErrorCode_t 	UserWrittenI2CWrite (tmUnitSelect_t tUnit, UInt32 AddrSize, UInt8* pAddr,UInt32 WriteLen, UInt8* pData);
tmErrorCode_t 	UserWrittenWait(tmUnitSelect_t tUnit, UInt32 tms);
tmErrorCode_t 	UserWrittenPrint(UInt32 level, const char* format, ...);
tmErrorCode_t  	UserWrittenMutexInit(ptmbslFrontEndMutexHandle *ppMutexHandle);
tmErrorCode_t  	UserWrittenMutexDeInit( ptmbslFrontEndMutexHandle pMutex);
tmErrorCode_t  	UserWrittenMutexAcquire(ptmbslFrontEndMutexHandle pMutex, UInt32 timeOut);
tmErrorCode_t  	UserWrittenMutexRelease(ptmbslFrontEndMutexHandle pMutex);


//*--------------------------------------------------------------------------------------
//* Template of function to be provided by customer
//*--------------------------------------------------------------------------------------

//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenI2CRead
//* Object              : 
//* Input Parameters    : 	tmUnitSelect_t tUnit
//* 						UInt32 AddrSize,
//* 						UInt8* pAddr,
//* 						UInt32 ReadLen,
//* 						UInt8* pData
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t UserWrittenI2CRead(tmUnitSelect_t tUnit,	UInt32 AddrSize, UInt8* pAddr,
UInt32 ReadLen, UInt8* pData)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/

	INT32 result = 0;
	UINT8 u8_add = (0xc0 & 0xff);

	if (AddrSize != 1)
	{
		TDA18250_PRINTF("TDA18250 error 2 !\n");
		
	}

	if (ReadLen > 15)
	{
		TDA18250_PRINTF("TDA18250 error 3 !\n");
	}

	pData[0] = pAddr[0];
	
	result = i2c_write_read(tda18250_tuner_i2c, u8_add, pData, 1, ReadLen);

	if (result == SUCCESS)
	{
		err = TM_OK;
	}
	else
	{
		err = !TM_OK;
	}

/* ...*/
/* End of Customer code here */

   return err;
}

//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenI2CWrite
//* Object              : 
//* Input Parameters    : 	tmUnitSelect_t tUnit
//* 						UInt32 AddrSize,
//* 						UInt8* pAddr,
//* 						UInt32 WriteLen,
//* 						UInt8* pData
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
#define BURST_SZ 14
tmErrorCode_t UserWrittenI2CWrite (tmUnitSelect_t tUnit, 	UInt32 AddrSize, UInt8* pAddr,
UInt32 WriteLen, UInt8* pData)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/
	INT32 result = 0;
	UINT8 data[BURST_SZ+1]; // every time, write 14 byte..

	INT32 RemainLen, BurstNum;
	INT32 i,j;

	UINT8 u8_add = (0xc0 & 0xff);

	if (AddrSize != 1)
	{
		TDA18250_PRINTF("TDA18250 error 1 !\n");
		
	}
	
	RemainLen = WriteLen % BURST_SZ; 
	if (RemainLen)
	{
		BurstNum = WriteLen / BURST_SZ; 
	}
	else
	{
		BurstNum = WriteLen / BURST_SZ - 1;
		RemainLen = BURST_SZ;
	}

	for ( i = 0 ; i < BurstNum; i ++ )
	{
		for ( j = 0 ; j < BURST_SZ ; j++  )
		{
			data[j+1]   = pData[i * BURST_SZ + j ];
		}
		data[0] = pAddr[0]+i*BURST_SZ;

		result |= i2c_write(tda18250_tuner_i2c, u8_add, data, BURST_SZ+1);

	}

	

	for ( i = 0 ; i < RemainLen ; i++ )
	{
		data[i+1]   = pData[BurstNum * BURST_SZ + i ];
		data[0] = pAddr[0]+BurstNum*BURST_SZ;
	}
	result |= i2c_write(tda18250_tuner_i2c, u8_add, data, RemainLen+1);

	if (result == SUCCESS)
	{
		err = TM_OK;
	}
	else
	{
		err = !TM_OK;
	}

	
/* ...*/
/* End of Customer code here */

   return err;
}

//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenWait
//* Object              : 
//* Input Parameters    : 	tmUnitSelect_t tUnit
//* 						UInt32 tms
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t UserWrittenWait(tmUnitSelect_t tUnit, UInt32 tms)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/
	osal_task_sleep(tms);
/* ...*/
/* End of Customer code here */

   return err;
}

//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenPrint
//* Object              : 
//* Input Parameters    : 	UInt32 level, const char* format, ...
//* 						
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t 			UserWrittenPrint(UInt32 level, const char* format, ...)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/

/* ...*/
/* End of Customer code here */

   return err;
}

//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenMutexInit
//* Object              : 
//* Input Parameters    : 	ptmbslFrontEndMutexHandle *ppMutexHandle
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t  UserWrittenMutexInit(ptmbslFrontEndMutexHandle *ppMutexHandle)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

	static UINT8 mux_cnt = 0;
	
	OSAL_ID tun_tda18250_mutex_id = OSAL_INVALID_ID;	//for i2c write and read mutec protection.

/* Customer code here */
/* ...*/

	tun_tda18250_mutex_id = osal_mutex_create();
	if(tun_tda18250_mutex_id == OSAL_INVALID_ID)	
	{
		TDA18250_PRINTF("i2c mutex error\n");
	}

	tun_tda18250_mutex_arr[mux_cnt] = tun_tda18250_mutex_id;
	
	*ppMutexHandle = (void*)&tun_tda18250_mutex_arr[mux_cnt];

	mux_cnt += 1;
/* ...*/
/* End of Customer code here */

   return err;
}


//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenMutexDeInit
//* Object              : 
//* Input Parameters    : 	 ptmbslFrontEndMutexHandle pMutex
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t  UserWrittenMutexDeInit( ptmbslFrontEndMutexHandle pMutex)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/
	osal_mutex_delete(*((OSAL_ID*)pMutex));
/* ...*/
/* End of Customer code here */

   return err;
}



//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenMutexAcquire
//* Object              : 
//* Input Parameters    : 	ptmbslFrontEndMutexHandle pMutex, UInt32 timeOut
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t  UserWrittenMutexAcquire(ptmbslFrontEndMutexHandle pMutex, UInt32 timeOut)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/
	osal_mutex_lock(*((OSAL_ID*)pMutex), timeOut);

/* ...*/
/* End of Customer code here */

   return err;
}

//*--------------------------------------------------------------------------------------
//* Function Name       : UserWrittenMutexRelease
//* Object              : 
//* Input Parameters    : 	ptmbslFrontEndMutexHandle pMutex
//* Output Parameters   : tmErrorCode_t.
//*--------------------------------------------------------------------------------------
tmErrorCode_t  UserWrittenMutexRelease(ptmbslFrontEndMutexHandle pMutex)
{
   /* Variable declarations */
   tmErrorCode_t err = TM_OK;

/* Customer code here */
/* ...*/
	osal_mutex_unlock(*((OSAL_ID*)pMutex));

/* ...*/
/* End of Customer code here */

   return err;
}

	
INT32 tun_tda18250_init(UINT32* tuner_id, struct QAM_TUNER_CONFIG_EXT * ptrTuner_Config)
{
	struct QAM_TUNER_CONFIG_EXT * tuner_dev_ptr = NULL;
	/* check Tuner Configuration structure is available or not */
	if ((ptrTuner_Config == NULL) || (tda18250_tuner_cnt>=MAX_TUNER_SUPPORT_NUM))
		return ERR_FAILUE;

	//reopen process;
	if(ptrTuner_Config->cTuner_reopen & 0xff)
	{
		tuner_dev_ptr=tda18250_dev_id[*tuner_id];
		tuner_dev_ptr->cTuner_freq_param=(ptrTuner_Config->cTuner_reopen & 0xFF00) >> 8;
		return SUCCESS;
	}

	tuner_dev_ptr = (struct QAM_TUNER_CONFIG_EXT *)MALLOC(sizeof(struct QAM_TUNER_CONFIG_EXT));
	if((void*)tuner_dev_ptr == NULL)
		return ERR_FAILUE;

	MEMCPY(tuner_dev_ptr, ptrTuner_Config, sizeof(struct QAM_TUNER_CONFIG_EXT));	
	
	tda18250_tuner_i2c = tuner_dev_ptr->i2c_type_id;
	tda18250_dev_id[tda18250_tuner_cnt] = tuner_dev_ptr;
	*tuner_id = tda18250_tuner_cnt;

	tda18250_tuner_cnt ++;

	TDA18250_PRINTF("%s start !\n", __FUNCTION__);
	
	return SUCCESS;
}

INT32 tun_tda18250_status(UINT32 tuner_id, UINT8 *lock)
{
	INT32 result = 0;
	tmErrorCode_t err;
	tmbslFrontEndState_t PLLLockMaster = tmbslFrontEndStateUnknown;	
	
	struct QAM_TUNER_CONFIG_EXT * tuner_dev_ptr = NULL;

	if ((tuner_id>=tda18250_tuner_cnt) || (tuner_id>=MAX_TUNER_SUPPORT_NUM))
		return ERR_FAILUE;
	tuner_dev_ptr = tda18250_dev_id[tuner_id];

   /* Get TDA18250 Master PLL Lock status */
	err = tmbslTDA18250GetLockStatus(0, &PLLLockMaster);
	if(err != TM_OK)
	{
		*lock = 0;
		result = !SUCCESS;
	}
	else
	{
		if (tmbslFrontEndStateLocked == PLLLockMaster)
		{
			*lock = 1;
		}
		else
		{
			*lock = 0;
		}
		result = SUCCESS;
	}
   
	return result;
}

INT32 tun_tda18250_control(UINT32 tuner_id, UINT32 freq, UINT32 sym, UINT8 AGC_Time_Const, UINT8 _i2c_cmd)	
{	

	INT32   result;
	tmErrorCode_t err;
	static INT8 tun_status=0;
	static UINT8 t_val=0x00;

	UInt32 uRFMaster = freq*1000;
	//UInt32 uIFMaster = 0;

	struct QAM_TUNER_CONFIG_EXT * tuner_dev_ptr = NULL;

	tuner_dev_ptr = tda18250_dev_id[tuner_id];
	if(tuner_dev_ptr->cTuner_freq_param !=0x00)
	{
		if(t_val!=tuner_dev_ptr->cTuner_freq_param)
		{
			t_val=tuner_dev_ptr->cTuner_freq_param;
			tun_status=0x00;
		}
	}
	

	if (0==tun_status)
	{
	   /* Variable declarations */
	   tmErrorCode_t err = TM_OK;
	   tmbslFrontEndDependency_t sSrvTunerFunc;

	   tmTDA18250StandardMode_t stdModeMaster = tmTDA18250_DIG_9MHz; //J83AC
	   switch(tuner_dev_ptr->cTuner_freq_param)
	   	{
	   		case 0x09:
				stdModeMaster=tmTDA18250_DIG_9MHz;
				break;
			case 0x0C:
				stdModeMaster=tmTDA18250_DIG_6MHz;
				break;
			default:
				stdModeMaster = tmTDA18250_DIG_9MHz;
				break;
	   	}
	tuner_dev_ptr->cTuner_freq_param =0x00;
#if 0   
	   tmTDA18250StandardMode_t stdModeMaster = tmTDA18250_DIG_6MHz; //J83B
#else
//	   tmTDA18250StandardMode_t stdModeMaster = tmTDA18250_DIG_8MHz; //J83AC
#endif	   
	/* Low layer struct set-up to link with user written functions */
	   sSrvTunerFunc.sIo.Write             = UserWrittenI2CWrite;
	   sSrvTunerFunc.sIo.Read              = UserWrittenI2CRead;
	   sSrvTunerFunc.sTime.Get             = Null;
	   sSrvTunerFunc.sTime.Wait            = UserWrittenWait;
	   sSrvTunerFunc.sDebug.Print          = UserWrittenPrint;
	   sSrvTunerFunc.sMutex.Init           = UserWrittenMutexInit;
	   sSrvTunerFunc.sMutex.DeInit         = UserWrittenMutexDeInit;
	   sSrvTunerFunc.sMutex.Acquire        = UserWrittenMutexAcquire;
	   sSrvTunerFunc.sMutex.Release        = UserWrittenMutexRelease;
	   sSrvTunerFunc.dwAdditionalDataSize  = 0;
	   sSrvTunerFunc.pAdditionalData       = Null;
	   
	   /* TDA18250 Master Driver low layer setup */
	   err = tmbslTDA18250Init(0, &sSrvTunerFunc);
	   if(err != TM_OK)
	       return err;
	   
	   /* TDA18250 Master Hardware initialization */
	   err = tmbslTDA18250Reset(0);
	   if(err != TM_OK)
	       return err;
	   
	   /* TDA18250 Master Hardware power state */
	   err = tmbslTDA18250SetPowerState(0, tmTDA18250_PowerNormalMode);
	   if(err != TM_OK)
	       return err;


	   /* TDA18250 Master standard mode */
	   err = tmbslTDA18250SetStandardMode(0, stdModeMaster);
	   if(err != TM_OK)
	       return err;

		tun_status = 1;
	}
	
   /* TDA18250 Master RF frequency */
   err = tmbslTDA18250SetRf(0, uRFMaster);
   if(err != TM_OK)
       return err;

	osal_task_sleep(100); // we don't know wait how long, just give a norminal value.   
   /* Get TDA18250 Master IF */
/*
   err = tmbslTDA18250GetIF(0, &uIFMaster);
   if(err != TM_OK)
       return err;
*/
	if (err !=TM_OK) 
	{
		result= ERR_FAILED;
	}
	else
	{
		result = SUCCESS;
	}

	return result;

}

